﻿using CommandProcessor.Dispatcher;
using Data.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PagedList;
using AutoMapper;
using QuanLySanXuat.Models;
using Domain.Commands;
using Core.Common;
using Core.Extensions;
using Data.Models;

namespace QuanLySanXuat.Controllers
{
    public class OrderController : Controller
    {
        private readonly ICommandBus commandBus;
        private readonly IUOMRepository uomRepository;
        private readonly IOrderRepository orderRepository;
        private readonly IProductModelRepository productModelRepository;
        private readonly IEmployeeRepository employeeRepository;
        private readonly IMaterialFormulaRepository materialFormulaRepository;
        private readonly IMaterialRepository materialRepository;
        private readonly IMaterialDetailRepository materialDetailRepository;
        private readonly ILabourDetailRepository labourDetailRepository;
        private readonly IOtherCostDetailRepository otherDetailRepository;
        private readonly IToolDetailRepository toolDetailRepository;
        private readonly ILabourFormulaRepository labourFormulaRepository;
        private readonly IWorkerLevelRepository labourRepository;
        private readonly ILevelNormRepository labourNormRepository;
        private readonly IToolFormulaRepository toolFormulaRepository;
        private readonly IToolTypeRepository toolTypeRepository;
        private readonly IToolNormRepository toolNormRepository;
        private readonly IBillOutRepository billDetaiRepository;
        private readonly IBillDetailRepository billmaterialRepository;
        private readonly IOtherCostRepository otherCostRepository;
        private readonly IOtherCostFormulaRepository otherFormulaRepository;
        private readonly IDesignDetailRepository desginDetailRepository;
        private readonly IMaterialTypeRepository materTypeRepository;

        public OrderController(ICommandBus commandBus, IOrderRepository orderRepository, IProductModelRepository productModelRepository, IEmployeeRepository employeeRepository, IMaterialFormulaRepository materialFormulaRepository, IMaterialRepository materialRepository, ILabourFormulaRepository labourFormulaRepository, IToolFormulaRepository toolFormulaRepository, IOtherCostFormulaRepository otherFormulaRepository, IBillOutRepository billDetaiRepository, IUOMRepository uomRepository, IToolTypeRepository toolTypeRepository, IToolNormRepository toolNormRepository, IWorkerLevelRepository labourRepository, ILevelNormRepository labourNormRepository, IOtherCostRepository otherCostRepository, IMaterialDetailRepository materialDetailRepository, ILabourDetailRepository labourDetailRepository, IOtherCostDetailRepository otherDetailRepository, IToolDetailRepository toolDetailRepository, IDesignDetailRepository desginDetailRepository, IBillDetailRepository billmaterialRepository, IMaterialTypeRepository materTypeRepository)
        {
            this.commandBus = commandBus;
            this.orderRepository = orderRepository;
            this.productModelRepository = productModelRepository;
            this.employeeRepository = employeeRepository;
            this.materialFormulaRepository=materialFormulaRepository;
            this.materialRepository=materialRepository;
            this.labourFormulaRepository=labourFormulaRepository;

            this.otherFormulaRepository=otherFormulaRepository;
            this.toolFormulaRepository=toolFormulaRepository;
            this.billDetaiRepository = billDetaiRepository;
            this.uomRepository = uomRepository;
            this.toolTypeRepository = toolTypeRepository;
            this.toolNormRepository = toolNormRepository;
            this.labourFormulaRepository = labourFormulaRepository;
            this.labourNormRepository = labourNormRepository;
            this.labourRepository = labourRepository;
            this.otherCostRepository = otherCostRepository;
            this.materialDetailRepository = materialDetailRepository;
            this.labourDetailRepository = labourDetailRepository;
            this.otherDetailRepository = otherDetailRepository;
            this.toolDetailRepository = toolDetailRepository;
            this.desginDetailRepository = desginDetailRepository;
            this.billmaterialRepository = billmaterialRepository;
            this.materTypeRepository = materTypeRepository;
        }
        //
        // GET: /Order/

        public ActionResult Index()
        {
            //Lay ra cac order chua duoc thuc hien san xuat Status=0;
            var oder = orderRepository.GetAll().OrderBy(x=>x.Status);
            return View(oder.ToPagedList(1, 10));
        }
        public ActionResult Create(int? ID)
        {
            ViewData["ProductModel"] = productModelRepository.GetAll();

            ViewData["Employee"] = employeeRepository.GetAll();
            //Dung thay doi material=>materialType 
            ViewData["Material"] = materialRepository.GetAll();

            ViewData["MaterialFormula"] = materialFormulaRepository.GetAll();
            ViewData["UOM"] = uomRepository.GetAll();
            ViewData["BillDetail"] = billDetaiRepository.GetAll();
            ViewData["ToolFormula"] = toolFormulaRepository.GetAll();
            ViewData["ToolType"] = toolTypeRepository.GetAll();
            ViewData["ToolNorm"] = toolNormRepository.GetAll();

            ViewData["LabourFormula"] = labourFormulaRepository.GetAll();
            ViewData["Labour"] = labourRepository.GetAll();
            ViewData["LabourNorm"] = labourNormRepository.GetAll();

            ViewData["OtherCostFormula"] = otherFormulaRepository.GetAll();
            ViewData["OtherCost"] = otherCostRepository.GetAll();

            var oder = orderRepository.GetById(ID ?? 0);
            var oderForm = Mapper.Map<Order, OrderFormModels>(oder);
            if (oder != null)
            { 
                //Lay ra danh sach cac quy dinh
                oderForm.MaterialDetailFormModels = materialDetailRepository.GetMany(x => x.OrderID == ID).ToList();
                oderForm.LabourDetailFormModels = labourDetailRepository.GetMany(x => x.OrderID == ID).ToList();
                oderForm.OtherCostDetailFormModels = otherDetailRepository.GetMany(x => x.OrderID == ID).ToList();
                oderForm.ToolDetailFormModels = toolDetailRepository.GetMany(x => x.OrderID == ID).ToList();
            }
            return View(oderForm);
        }
        [HttpPost]
        public ActionResult RemoveItems(string[] ProID)
        {
            List<DeleteOrderCommand> listt = new List<DeleteOrderCommand>();
            foreach (var e in ProID)
            {
                var oderID = int.Parse(e);

                //Xoa vao bang MaterialFormual ghi tam voi ProductModel hien tai
                var materialDetail = materialDetailRepository.GetMany(x => x.OrderID == oderID);
                if (materialDetail.Count() > 0)
                {
                    List<DeleteMaterialDetailCommand> list = new List<DeleteMaterialDetailCommand>();
                    foreach (var item in materialDetail)
                    {
                        var cmd = new DeleteMaterialDetailCommand { ID = item.ID };
                        list.Add(cmd);
                    }
                    commandBus.SubmitRange(list);
                }

                //Xoa vao bang TollFormual ghi tam voi ProductModel hien tai
                var tool = toolDetailRepository.GetMany(x => x.OrderID == oderID);
                if (tool.Count() > 0)
                {
                    List<DeleteToolDetailCommand> list = new List<DeleteToolDetailCommand>();
                    foreach (var item in tool)
                    {
                        var cmd = new DeleteToolDetailCommand { ID = item.ID };
                        list.Add(cmd);
                    }
                    commandBus.SubmitRange(list);
                }

                //Xoa vao bang OtherFormual ghi tam voi ProductModel hien tai
                var other = otherDetailRepository.GetMany(x => x.OrderID == oderID);
                if (other.Count() > 0)
                {
                    List<DeleteOtherCostDetailCommand> list = new List<DeleteOtherCostDetailCommand>();
                    foreach (var item in other)
                    {
                        var cmd = new DeleteOtherCostDetailCommand { ID = item.ID };
                        list.Add(cmd);
                    }
                    commandBus.SubmitRange(list);
                }

                //Xoa vao bang LabourFormual ghi tam voi ProductModel hien tai
                var labour = labourDetailRepository.GetMany(x => x.OrderID == oderID);
                if (labour.Count() > 0)
                {
                    List<DeleteLabourDetailCommand> list = new List<DeleteLabourDetailCommand>();
                    foreach (var item in labour)
                    {
                        var cmd = new DeleteLabourDetailCommand { ID = item.ID };
                        list.Add(cmd);
                    }
                    commandBus.SubmitRange(list);
                }

                var oder = new DeleteOrderCommand { ID = oderID };
                listt.Add(oder);
            }
            //Xoa bang Oder
            commandBus.SubmitRange(listt);
            var model = orderRepository.GetMany(x => x.Status == 0);
            return PartialView("_OrderList", model.ToPagedList(1, 10));
        }
        [HttpPost]
        public ActionResult Approve(string[] ProID)
        {
            List<CreateOrUpdateOrderCommand> listt = new List<CreateOrUpdateOrderCommand>();
            foreach (var e in ProID)
            {
                var oderID = int.Parse(e);
                var odercom=orderRepository.GetById(oderID);
                var command = Mapper.Map<Order, OrderFormModels>(odercom);
                var oder = Mapper.Map<OrderFormModels, CreateOrUpdateOrderCommand>(command);
                oder.Status = 1;
                listt.Add(oder);
            }
            //Cap nhat
            commandBus.SubmitRange(listt);
            var model = orderRepository.GetMany(x => x.Status == 0);
            return PartialView("_OrderList", model.ToPagedList(1, 10));
        }
        [HttpPost]
        public ActionResult Save(OrderFormModels frm)
        {
            //Them vao bang Order
            var form = new OrderFormModels()
            {
                BillDetailID = frm.BillDetailID,
                Code = frm.Code,
                Date1 = frm.Date1,
                Date2 = frm.Date2,
                StartDate = frm.StartDate,
                EndDate = frm.EndDate,
                ID = frm.ID,
                User1ID = frm.User1ID,
                User2ID = frm.User2ID,
                ProductModelID = frm.ProductModelID,
                Quantity = frm.Quantity,
                Note = frm.Note,
                Status = 0,//Chua duoc duyet
            };
            var command = Mapper.Map<OrderFormModels, CreateOrUpdateOrderCommand>(form);
            IEnumerable<ValidationResult> errors = commandBus.Validate(command);
            ModelState.AddModelErrors(errors);

            var result = commandBus.Submit(command);

            /// Them vao bang MaterialDetail
            /// 
            if (frm.MaterialDetailID != null)
            {
                var lst = new List<CreateOrUpdateMaterialDetailCommand>();
                for (int i = 0; i < frm.MaterialDetailID.Length; i++)
                {
                    var frmDetail = new MaterialDetailFormModels()
                    {
                        BillDetailID = frm.BillDetailID[i],
                        Code = frm.MaterialDetailCode[i],
                        ID = frm.MaterialDetailID[i],
                        MaterialFormulaID = frm.MaterialFormulaID[i],
                        MaterialID = frm.MaterialID[i],
                        OrderID = result.ID,
                        Price = frm.Price[i],
                        ProductModelID = frm.ProductModelID ?? 0,
                        Quantity = frm.MaterialDetailQuantity[i],
                        UOMID = frm.MaterialDetailUOMID[i]
                    };
                    var cmdMater = Mapper.Map<MaterialDetailFormModels, CreateOrUpdateMaterialDetailCommand>(frmDetail);
                    lst.Add(cmdMater);
                }
                commandBus.SubmitRange(lst);
            }

                /// Them vao bang ToolDetail
                /// 
            if (frm.ToolDetailID != null)
            {
                var lstTool = new List<CreateOrUpdateToolDetailCommand>();
                for (int i = 0; i < frm.ToolDetailID.Length; i++)
                {
                    var frmDetail = new ToolDetailFormModels()
                    {
                        Code = frm.ToolDetailCode[i],
                        ID = frm.ToolDetailID[i],
                        OrderID = result.ID,
                        ProductModelID = frm.ProductModelID ?? 0,
                        Quantity = frm.ToolDetailQuantity[i],
                        ToolFormulaID = frm.ToolFormulaID[i],
                        ToolNormID = frm.ToolNormID[i],
                        ToolTypeID = frm.ToolTypeID[i],
                        UOM1ID = frm.ToolDetailUOM1ID[i],
                        UOMID2 = frm.ToolDetailUOMID2[i],
                        Norm = frm.ToolDetailNorm[i],
                    };
                    var cmdMater = Mapper.Map<ToolDetailFormModels, CreateOrUpdateToolDetailCommand>(frmDetail);
                    lstTool.Add(cmdMater);
                }
                commandBus.SubmitRange(lstTool);
            }

             /// Them vao bang LabourDetail
            if (frm.LabourDetailID != null)
            {
                var lstLabour = new List<CreateOrUpdateLabourDetailCommand>();
                for (int i = 0; i < frm.LabourDetailID.Length; i++)
                {
                    var frmDetail = new LabourDetailFormModels()
                    {
                        Code = frm.LabourDetailCode[i],
                        ID = frm.LabourDetailID[i],
                        OrderID = result.ID,
                        ProductModelID = frm.ProductModelID ?? 0,
                        Quantity = frm.LabourDetailQuantity[i],
                        LabourFormulaID=frm.LabourFormulaID[i],
                        LevelID=frm.LevelID[i],
                        LevelNormID = frm.LevelNormID[i],
                        Norm = frm.LabourDetailNorm[i],
                        UOMID = frm.LabourDetailUOMID[i],
                        UOMID2 = frm.LabourDetailUOMID2[i],
                    };
                    var cmdMater = Mapper.Map<LabourDetailFormModels, CreateOrUpdateLabourDetailCommand>(frmDetail);
                    lstLabour.Add(cmdMater);
                }
                commandBus.SubmitRange(lstLabour);
            }

            /// Them vao bang OtherDetail
            if (frm.OtherCostDetailID != null)
            {
                var lstOther= new List<CreateOrUpdateOtherCostDetailCommand>();
                for (int i = 0; i < frm.OtherCostDetailID.Length; i++)
                {
                    var frmDetail = new OtherCostDetailFormModels()
                    {
                        Code = frm.OtherCostDetailCode[i],
                        ID = frm.OtherCostDetailID[i],
                        OrderID = result.ID,
                        ProductModelID = frm.ProductModelID ?? 0,
                        Quantity = frm.OtherCostDetailQuantity[i],
                        UOMID = frm.OtherCostDetailUOMID[i],
                        OtherCostFormulaID = frm.OtherCostFormulaID[i],
                        OtherCostID=frm.OtherCostID[i],
                        Norm = frm.OtherCostDetailNorm[i]
                        
                    };
                    var cmdMater = Mapper.Map<OtherCostDetailFormModels, CreateOrUpdateOtherCostDetailCommand>(frmDetail);
                    lstOther.Add(cmdMater);
                }
                commandBus.SubmitRange(lstOther);
            }
            return RedirectToAction("Index");
        }
        [HttpGet]
        public JsonResult GetMaterialFormula(int ID)
        {
            var material = materialFormulaRepository.GetMany(x => x.ProductModelID == ID);
            if (material.Count()==0)
            {
                return Json(materialFormulaRepository.GetAll() as IEnumerable<MaterialFormulaFormModels>, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(new {material}, JsonRequestBehavior.AllowGet);
            }
        }
        [HttpGet]
        public JsonResult GetLabourFormula(int ID)
        {
            var labour = labourFormulaRepository.GetMany(x => x.ProductModelID == ID);
            if (labour.Count() == 0)
            {
                return Json(ViewData["LabourFormula"] as IEnumerable<Data.Models.LabourFormula>, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(labour as IEnumerable<Data.Models.LabourFormula>, JsonRequestBehavior.AllowGet);
            }
        }
        [HttpGet]
        public JsonResult GetToolFormula(int ID)
        {
            var tool = toolFormulaRepository.GetMany(x => x.ProductModelID == ID);
            if (tool.Count() == 0)
            {
                return Json(ViewData["ToolFormula"] as IEnumerable<Data.Models.ToolFormula>, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(tool as IEnumerable<Data.Models.ToolFormula>, JsonRequestBehavior.AllowGet);
            }
        }
        [HttpGet]
        public JsonResult GetOtherFormula(int ID)
        {
            var other = otherFormulaRepository.GetMany(x => x.ProductModelID == ID);
            if (other.Count() == 0)
            {
                return Json(ViewData["OtherCostFormula"] as IEnumerable<Data.Models.OtherCostFormula>, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(other as IEnumerable<Data.Models.OtherCostFormula>, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpGet]
        public ActionResult GetDetail(int ID)
        {
            var model = new OrderFormModels();
            var desgin = desginDetailRepository.GetMany(x => x.ProductModelID == ID);
            List<MaterialDetail> materialDetailFormModels= new List<MaterialDetail>();
            List<LabourDetail> labourDetailFormModels = new List<LabourDetail>();
            List<ToolDetail> toolDetailFormModels = new List<ToolDetail>();
            List<OtherCostDetail> otherCostDetailFormModels = new List<OtherCostDetail>();
            foreach (var item in desgin)
            {
                var materials = materialFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                foreach (var material in materials)
                {
                    //Lay ra theo phieu xuat
                    var billout = billmaterialRepository.GetMany(x => x.MaterialID == material.ID);
                    var materialfml = new MaterialDetail()
                    {
                        MaterialFormulaID = material.ID,
                        UOMID = material.UOMID ?? 0,
                        Quantity = material.Quantity,
                        //Bill = billout,
                    };
                    materialDetailFormModels.Add(materialfml);
                }

                //Labour
                var labours = labourFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                foreach (var labour in labours)
                {
                    var labourfml = new LabourDetail()
                    {
                        LabourFormulaID=labour.ID,
                        UOMID=labour.UOMID,
                        Quantity=labour.Quantity,
                        LevelID=labour.WorkerLevelID
                    };
                    labourDetailFormModels.Add(labourfml);
                }
                //tool
                var tools = toolFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                foreach (var tool in tools)
                {
                    var toolfml = new ToolDetail()
                    {
                        ToolFormulaID = tool.ID,
                        ToolTypeID = tool.ToolTypeID,
                        UOM1ID = tool.UOMID,
                        Quantity = tool.Quantity
                    };
                   toolDetailFormModels.Add(toolfml);
                }
                //Other
                var others = otherFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                foreach (var other in others)
                {
                    var otherfml = new OtherCostDetail()
                    {
                        OtherCostFormulaID = other.ID,
                        UOMID = other.UOMID,
                        OtherCostID = other.OtherCostID,
                        Quantity=other.Quantity,
                    };
                    otherCostDetailFormModels.Add(otherfml);
                }
            }
            model.OtherCostDetailFormModels = otherCostDetailFormModels;
            model.ToolDetailFormModels = toolDetailFormModels;
            model.MaterialDetailFormModels = materialDetailFormModels;
            model.LabourDetailFormModels = labourDetailFormModels;

            ViewData["ProductModel"] = productModelRepository.GetAll();

            ViewData["Employee"] = employeeRepository.GetAll();
            ViewData["Material"] = materialRepository.GetAll();
            ViewData["MaterialFormula"] = materialFormulaRepository.GetAll();
            ViewData["UOM"] = uomRepository.GetAll();
            ViewData["BillDetail"] = billDetaiRepository.GetAll();
            ViewData["ToolFormula"] = toolFormulaRepository.GetAll();
            ViewData["ToolType"] = toolTypeRepository.GetAll();
            ViewData["ToolNorm"] = toolNormRepository.GetAll();

            ViewData["LabourFormula"] = labourFormulaRepository.GetAll();
            ViewData["Labour"] = labourRepository.GetAll();
            ViewData["LabourNorm"] = labourNormRepository.GetAll();

            ViewData["OtherCostFormula"] = otherFormulaRepository.GetAll();
            ViewData["OtherCost"] = otherCostRepository.GetAll();
            return PartialView("_OrderDetails",model);
        }
        [HttpGet]
        public JsonResult GetPrice(int Code, int MaterialID)
        {
            double? price = 0;
            if (billmaterialRepository.GetMany(x => x.BillOutID == Code && x.MaterialID == MaterialID).Count() > 0)
            {
                price = billmaterialRepository.GetMany(x => x.BillOutID == Code && x.MaterialID == MaterialID).FirstOrDefault().Price_Out;
            }
            return Json(price, JsonRequestBehavior.AllowGet);
        }
        [HttpGet]
        public JsonResult GetNorm(int Code, string Name)
        {
            int uomID = 0;
            int norm = 0;
           if (Name == "tblTool")
            {
               var Norm=toolNormRepository.GetById(Code);
               if (Norm != null)
               {
                   uomID = Norm.UOMID ?? 0;
                   norm = Norm.Norm ?? 0;
               }
              
            }
            else if (Name == "tblLabour")
            {
                var Norm = labourNormRepository.GetById(Code);
                if (Norm != null)
                {
                    uomID = Norm.UOMID ?? 0;
                    norm = Norm.Norm ?? 0;
                }

            }
            else if (Name == "tblOther")
            {
                var Norm = otherCostRepository.GetById(Code);
                if (Norm != null)
                {
                    uomID = Norm.UOMID;
                    norm = Norm.Norm ?? 0;
                }
            }
            return Json(new { Unit = uomID, Norm = norm }, JsonRequestBehavior.AllowGet);
        }
        [HttpGet]
        [ValidateInput(false)]
        public ActionResult Page(int PageID)
        {
            var oder = orderRepository.GetAll().OrderBy(x => x.Status);
            return PartialView("_OrderList", oder.ToPagedList(1, PageID));
        }
        [HttpGet]
        public ActionResult Search(string Name)
        {
            IEnumerable<Order> model;
            if (String.IsNullOrEmpty(Name))
            {
                model = orderRepository.GetAll();
            }
            else
            {
                model = orderRepository.GetMany(x => (x.Code.Contains(Name)) || (x.Employee.Name.Contains(Name)) || (x.ProductModel.Name.Contains(Name)));

            }
            return PartialView("_OrderList", model.ToPagedList(1, 10));
        }
    }
}
